package ve.com.wayoyo.wuml_case.DibujoDiagramas;

import java.util.ArrayList;

import ve.com.wayoyo.wuml_case.Painter;
import ve.com.wayoyo.wuml_case.UserPref;
import ve.com.wayoyo.wuml_case.Exceptions.MultiplicityException;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;

public class CompInterface extends Componente {

	static final int textMargin = 15;

	private Paint _borderPaint = Painter.getInstancia().getDefaultBorderPaint();
	private Path _borderPath = new Path();
	private String longestString;
	private ArrayList<CompMetodo> _metodos = new ArrayList<CompMetodo>();

	public CompInterface(String Titulo) {
		if (UserPref.getInstancia().isUsingConvections() && Titulo.length() > 1) {
			this.Titulo = Titulo.substring(0, 1).toUpperCase()
					+ Titulo.substring(1);
		} else {
			this.Titulo = Titulo;
		}
		_centerPoint = new Point();
		Point punto = new Point();
		punto.x = 20;
		punto.y = 20;
		this.setAnchor(punto);
		_width = Painter.getInstancia().getTextPaint(false, 1)
				.measureText(Titulo)
				+ textMargin;
		longestString = Titulo;
		if (_width < Painter.getInstancia().getTextPaint(true, 1)
				.measureText("<<Interface>>")
				+ textMargin) {
			_width = Painter.getInstancia().getTextPaint(true, 1)
					.measureText("<<Interface>>")
					+ textMargin;
			longestString = "<<Interface>>";
		}

		_connectionPoints = new Point[16];
		_connectionPointsCost = new int[16];
		float cpDistX = _width / 5;
		float cpDistY = _height / 5;
		for (int i = 0; i < 4; i++) {
			_connectionPoints[i] = new Point(
					(int) (Anchor.x + ((i + 1) * cpDistX)), Anchor.y);
		}
		for (int i = 4; i < 8; i++) {
			_connectionPoints[i] = new Point((int) (Anchor.x + _width),
					(int) (Anchor.y + ((i - 3) * cpDistY)));
		}
		for (int i = 8; i < 12; i++) {
			_connectionPoints[i] = new Point(
					(int) ((Anchor.x + _width) - ((i - 7) * cpDistX)),
					(int) (Anchor.y + _height));
		}
		for (int i = 12; i < 16; i++) {
			_connectionPoints[i] = new Point(Anchor.x,
					(int) ((Anchor.y + _height) - ((i - 11) * cpDistY)));
		}

		_height = 100;
		_topAnchors = new BorderAnchors(4, Anchor, new Point(
				(int) (Anchor.x + _width), Anchor.y));
		_bottomAnchors = new BorderAnchors(4, new Point(Anchor.x,
				(int) (Anchor.y + _height)), new Point(
				(int) (Anchor.x + _width), (int) (Anchor.y + _height)));
		_leftAnchors = new BorderAnchors(4, Anchor, new Point((int) (Anchor.x),
				(int) (Anchor.y + _height)));
		_rightAnchors = new BorderAnchors(4, new Point(
				(int) (Anchor.x + _width), (int) (Anchor.y)), new Point(
				(int) (Anchor.x + _width), (int) (Anchor.y + _height)));
	}

	@Override
	public void Dibujar(Canvas c, boolean isFcoused, float globalScale,
			int offSetX, int offSetY) {
		int posX = Anchor.x + offSetX;
		int posY = Anchor.y + offSetY;
		Paint _textPaint = Painter.getInstancia().getTextPaint(true,
				globalScale);

		_width = _textPaint.measureText(longestString) / globalScale
				+ textMargin;

		_borderPath.reset();
		_borderPath.moveTo(posX * globalScale, posY * globalScale);
		_borderPath.lineTo((posX + _width) * globalScale, posY * globalScale);
		_borderPath.lineTo((posX + _width) * globalScale, (posY + _height)
				* globalScale);
		_borderPath.lineTo(posX * globalScale, (posY + _height) * globalScale);
		_borderPath.close();
		c.drawPath(_borderPath,
				Painter.getInstancia().getBorderPaint(_currentState));

		/*
		 * //Dibujamos el Cuadro
		 * c.drawLine(posX*globalScale,posY*globalScale,(posX
		 * +_width)*globalScale
		 * ,posY*globalScale,Painter.getInstancia().getBorderPaint
		 * (_currentState));
		 * c.drawLine(posX*globalScale,posY*globalScale,posX*globalScale
		 * ,(posY+_height
		 * )*globalScale,Painter.getInstancia().getBorderPaint(_currentState));
		 * c.drawLine(posX*globalScale,(posY+_height)*globalScale,(posX+_width)*
		 * globalScale
		 * ,(posY+_height)*globalScale,Painter.getInstancia().getBorderPaint
		 * (_currentState));
		 * c.drawLine((posX+_width)*globalScale,posY*globalScale
		 * ,(posX+_width)*globalScale
		 * ,(posY+_height)*globalScale,Painter.getInstancia
		 * ().getBorderPaint(_currentState));
		 */

		// Dibujamos la linea del titulo
		c.drawLine(posX * globalScale, (posY + 60) * globalScale,
				(posX + _width) * globalScale, (posY + 60) * globalScale,
				_borderPaint);

		// Dibujamos el <<Interface>>
		float textSize = _textPaint.measureText("<<Interface>>");
		float distToMid = (((_width) * globalScale) - textSize) / 2;
		c.drawText("<<Interface>>", (posX * globalScale) + distToMid,
				(posY + 25) * globalScale, _textPaint);

		// Dibujamos el titulo
		textSize = _textPaint.measureText(Titulo);
		distToMid = (((_width) * globalScale) - textSize) / 2;
		c.drawText(Titulo, (posX * globalScale) + distToMid, (posY + 55)
				* globalScale, _textPaint);

		_textPaint = Painter.getInstancia().getTextPaint(false, globalScale);

		// Dibujamos los atributos
		int puntoEscritura = 0;

		// Dibujamos los metodos
		for (CompMetodo value : _metodos) {
			puntoEscritura += 30;
			if (value.isStatic()) {
				_textPaint.setUnderlineText(true);
				c.drawText(value.getText(), (posX + 5) * globalScale,
						(posY + 60 + puntoEscritura) * globalScale, _textPaint);
				_textPaint.setUnderlineText(false);
			} else {
				c.drawText(value.getText(), (posX + 5) * globalScale,
						(posY + 60 + puntoEscritura) * globalScale, _textPaint);
			}
		}

		// Dibujamos Los conectores Padre
		for (CompConector value : _conectorsBegining) {
			value.Dibujar(c, isFcoused, globalScale, offSetX, offSetY);
		}

		_textPaint.setTextSize(25);
	}

	@Override
	public boolean CalcularVisibilidad(int offSetX, int offSetY,
			float GlobalScale) {
		boolean Visible = true;
		if ((Anchor.x + _width) <= offSetX) {
			Visible = false;
		} else if (Anchor.x <= offSetX + UserPref.getInstancia().getWinWidth()) {
			Visible = false;
		} else if (Anchor.y > offSetY + UserPref.getInstancia().getWinHeight()) {
			Visible = false;
		} else if ((Anchor.y + _height) <= offSetY) {
			Visible = false;
		}
		return Visible;
	}

	@Override
	public boolean calcularTouch(Point touch) {
		boolean respuesta = false;
		if ((touch.x <= Anchor.x + _width) && (touch.x >= Anchor.x)) {
			if ((touch.y <= Anchor.y + _height) && (touch.y >= Anchor.y)) {
				respuesta = true;
				// FactoryPopup.getPopup(VistaDiagrama.getVista(), "Clases");
			}
		}
		return respuesta;
	}

	public void calculoLongitud() {
		Paint textPaint = Painter.getInstancia().getTextPaint(false, 1);
		_width = textPaint.measureText(Titulo) + textMargin;
		if (_width < textPaint.measureText("<<Interface>>") + textMargin) {
			_width = textPaint.measureText("<<Interface>>") + textMargin;
		}
		_height = 100;
		if (_metodos.size() == 0) {
			_height += 30;
		} else {
			for (CompMetodo met : _metodos) {
				if (_width - 10 < textPaint.measureText(met.getText())) {
					_width = textPaint.measureText(met.getText()) + textMargin;
					longestString = met.getText();
				}
				_height += 30;
			}
		}

		actualizarAchorsPoints();
		actualizarPuntoCentral();
	}

	public void addMetodo(CompMetodo nuevo) {
		_metodos.add(nuevo);
		Paint textPaint = Painter.getInstancia().getTextPaint(false, 1);
		if (_width - 10 < textPaint.measureText(nuevo.getText())) {
			_width = textPaint.measureText(nuevo.getText()) + textMargin;
			longestString = nuevo.getText();
		}
		_height += 30;
		actualizarPuntoCentral();
		actualizarAchorsPoints();
	}

	@Override
	public void setTitulo(String titulo) {
		Paint textPaint = Painter.getInstancia().getTextPaint(false, 1);
		if (UserPref.getInstancia().isUsingConvections()) {
			this.Titulo = titulo.substring(0, 1).toUpperCase()
					+ titulo.substring(1);
			if (_width - 10 < textPaint.measureText(Titulo)) {
				_width = textPaint.measureText(Titulo) + textMargin;
				longestString = Titulo;
			}
		} else {
			this.Titulo = titulo;
		}
		actualizarPuntoCentral();
	}

	@Override
	public CompConector calcularTouchConectores(Point touch) {
		for (CompConector value : _conectorsBegining) {
			if (value.calcularTouch(touch) == true)
				return value;
		}
		return null;
	}

	@Override
	public void actualizarPuntoCentral() {
		_centerPoint.set((Anchor.x + (int) (_width / 2)),
				(Anchor.y + (int) (_height / 2)));
	}

	@Override
	public void actualizarAchorsPoints() {
		_topAnchors.actualizar(Anchor, new Point((int) (Anchor.x + _width),
				Anchor.y));
		_bottomAnchors.actualizar(new Point(Anchor.x,
				(int) (Anchor.y + _height)), new Point(
				(int) (Anchor.x + _width), (int) (Anchor.y + _height)));
		_leftAnchors.actualizar(Anchor, new Point((int) (Anchor.x),
				(int) (Anchor.y + _height)));
		_rightAnchors.actualizar(new Point((int) (Anchor.x + _width),
				(int) (Anchor.y)), new Point((int) (Anchor.x + _width),
				(int) (Anchor.y + _height)));

		float cpDistX = _width / 5;
		float cpDistY = _height / 5;
		for (int i = 0; i < 4; i++) {
			_connectionPoints[i].set((int) (Anchor.x + ((i + 1) * cpDistX)),
					Anchor.y);
		}
		for (int i = 4; i < 8; i++) {
			_connectionPoints[i].set((int) (Anchor.x + _width),
					(int) (Anchor.y + ((i - 3) * cpDistY)));
		}
		for (int i = 8; i < 12; i++) {
			_connectionPoints[i].set(
					(int) ((Anchor.x + _width) - ((i - 7) * cpDistX)),
					(int) (Anchor.y + _height));
		}
		for (int i = 12; i < 16; i++) {
			_connectionPoints[i].set((int) (Anchor.x),
					(int) ((Anchor.y + _height) - ((i - 11) * cpDistY)));
		}

		Diagrama diagramaActual = null;
		if (VistaDiagrama.getVista() != null) {
			diagramaActual = VistaDiagrama.getVista().getDiagrama();
			for (CompConector value : _conectorsEnd) {
				value.actualizarRuta(diagramaActual.getComponenteById(value
						.get_fatherId()));
			}
		}
		for (CompConector value : _conectorsBegining) {
			value.actualizarRuta(this);
		}

	}

	public ArrayList<CompMetodo> get_metodos() {
		return _metodos;
	}

	public void set_metodos(ArrayList<CompMetodo> _metodos) {
		this._metodos = _metodos;
	}

	public CompMetodo getMetodoIndex(int index) {
		return this._metodos.get(index);
	}

	@Override
	public String generarDOM() {
		String DOM = "\t<Componente Tipo=\"Interface\" Titulo=\"" + Titulo
				+ "\" ID=\"" + ID + "\" AnchorX=\"" + Anchor.x
				+ "\" AnchorY=\"" + Anchor.y + "\">\n";

		for (CompMetodo value : _metodos) {
			DOM = DOM + value.generarDOM();
		}
		DOM = DOM + "\t</Componente>\n";
		return DOM;
	}

	@Override
	public String getConectorsDOM() {
		String DOM = "";
		for (CompConector value : _conectorsBegining) {
			DOM = DOM + value.generarDOM();
		}
		return DOM;
	}

	public String getCode(String Lenguaje) throws MultiplicityException {
		String code = "";
		Diagrama diagrama = VistaDiagrama.getVista().getDiagrama();
		if (diagrama instanceof DiagramaClases) {
			DiagramaClases diagramaClase = (DiagramaClases) diagrama;
			if (UserPref.getInstancia().getLanguaje().equals("C#"))
				code = "namespace " + diagramaClase.getPackageName() + "\n{\n";
			else
				code = "package " + diagramaClase.getPackageName() + ";\n\n";

			if (UserPref.getInstancia().getLanguaje().equals("C#"))
				code = code + "\tinterface " + Titulo;
			else
				code = code + "public interface " + Titulo;

			code = code + "{\n\n";

			for (CompMetodo value : _metodos) {
				if (UserPref.getInstancia().getLanguaje().equals("C#"))
					code = code + "\t\t"
							+ value.getCode(Lenguaje, false, false) + "\n";
				else
					code = code + "\t" + value.getCode(Lenguaje, false, false)
							+ "\n";
			}
			if (UserPref.getInstancia().getLanguaje().equals("C#"))
				code = code + "\n\t}\n}\n";
			else
				code = code + "\n}";
		}
		return code;
	}

	public void eliminarMetodo(int position) {
		this.get_metodos().remove(position);
		calculoLongitud();
	}

	public Boolean validMethod(CompMetodo nuevo) {
		String stNuevo = nuevo.getDefinition();
		Boolean flag = false;
		for (CompMetodo metodo : this._metodos) {
			if ((metodo.getDefinition().equalsIgnoreCase(stNuevo))&&(flag)) {
				return false;
			}else if ((metodo.getDefinition().equalsIgnoreCase(stNuevo))&&(!flag))
				flag = true;
		}
		return true;
	}

	@Override
	public String getTipo() {
		return "Interface";
	}

}
